﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace BlueCurve.Common.IO
{
    /// <summary>
    /// Fournit des méthodes de gestions du système de fichier
    /// </summary>
    public class CommonStream
    {
        /// <summary>
        /// Méthode native vérifiant si un répertoire est vide
        /// </summary>
        /// <param name="pszPath">Chemin du répertoire à tester</param>
        /// <returns>bool</returns>
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
        private extern static bool PathIsDirectoryEmpty(string pszPath);

        /// <summary>
        /// Méthode native transformant un nom long en nom court
        /// </summary>
        /// <param name="path">Chemin de base</param>
        /// <param name="shortPath">Objet stringbuilder</param>
        /// <param name="shortPathLength">Taille maximal du chemin de fichier court</param>
        /// <returns>int</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath, int shortPathLength);



        /// <summary>
        /// Copie un stream dans un autre
        /// de façon asynchrone
        /// http://msdn.microsoft.com/fr-fr/magazine/cc337900.aspx
        /// </summary>
        /// <param name="source">Stream source</param>
        /// <param name="destination">Stream destination</param>
        /// <param name="completed">Action()</param>
        public static void CopyStreamToStream(Stream source, Stream destination,
                                              Action<Stream, Stream, Exception> completed)
        {
            byte[] buffer = new byte[0x1000];
            System.ComponentModel.AsyncOperation asyncOp = System.ComponentModel.AsyncOperationManager.CreateOperation(null);

            Action<Exception> done = e =>
            {
                if (completed != null) asyncOp.Post(delegate
                {
                    completed(source, destination, e);
                }, null);
            };

            AsyncCallback rc = null;
            rc = readResult =>
            {
                try
                {
                    int read = source.EndRead(readResult);
                    if (read > 0)
                    {
                        destination.BeginWrite(buffer, 0, read, writeResult =>
                        {
                            try
                            {
                                destination.EndWrite(writeResult);
                                source.BeginRead(
                                    buffer, 0, buffer.Length, rc, null);
                            }
                            catch (Exception exc) { done(exc); }
                        }, null);
                    }
                    else done(null);
                }
                catch (Exception exc) { done(exc); }
            };
            source.BeginRead(buffer, 0, buffer.Length, rc, null);
        }


        /// <summary>
        /// Vérifie qu'un répertoire est vide
        /// </summary>
        /// <param name="path">Chemin de fichier du répertoire</param>
        /// <returns>bool</returns>
        public static bool DirectoryIsEmpty(string path)
        {
            return PathIsDirectoryEmpty(path);
        }


        /// <summary>
        /// Transforme un nom de fichier long en nom de fichier court
        /// </summary>
        /// <param name="path">Chemin de fichier à transformer</param>
        public static string LongToShortPath(string path)
        {
            StringBuilder shortPath = new StringBuilder(255);
            int result = GetShortPathName(path, shortPath, shortPath.Capacity);
            return shortPath.ToString();
        }
    }
}
